var	MONTH_SUM_DAY		= new Array(0,31,59,90,120,151,181,212,243,273,304,334,365);
var	MAX_DAY_IN_MONTH	= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
var	LMONTH_SUM_DAY		= new Array(0,31,60,91,121,152,182,213,244,274,305,335,366);
var	LMAX_DAY_IN_MONTH	= new Array(0,31,29,31,30,31,30,31,31,30,31,30,31);

ihelpuoo.util.Date = function(year,month,day)
{
	if(ihelpuoo.isString(year))
	{
		this.valueOf(year);
	}
	else
	{
		this.year = (year?year:0);
		this.month = (month?month:0);
		this.day = (day?day:0);
	}
	this._ily	= -1;	/* -1, without init, 0 leap year, 1 normal year*/
}

ihelpuoo.util.Date.prototype
=
{
	valueOf: function(s)
	{
		var i;
		var sb = "";
		for(i=0;i<s.length;i++)
		{
			if(ihelpuoo.codeIsNumber(s.charCodeAt(i)))break;
		}
		for(;i<s.length;i++)
		{
			if(!ihelpuoo.codeIsNumber(s.charCodeAt(i)))
			{
				this.year = ihelpuoo.parseInt(sb);
				break;
			}
			sb += s.charAt(i);
		}
		i++;
		sb = "";
		for(;i<s.length;i++)
		{
			if(!ihelpuoo.codeIsNumber(s.charCodeAt(i)))
			{
				this.month = ihelpuoo.parseInt(sb);
				break;
			}
			sb += s.charAt(i);
		}
		i++;
		sb = "";
		for(;i<s.length;i++)
		{
			if(!ihelpuoo.codeIsNumber(s.charCodeAt(i)))
				break;
			sb += s.charAt(i);
		}
		this.day = ihelpuoo.parseInt(sb);
		return i;
	}

	,
	offsetDay: function(day)
	{
		if (day == 0)
			return;
		if (day > 0)
			for (var i = 0; i < day; i++)
				this.addOneDay();
		else
			for (var i = day; i < 0; i++)
				this.minusOneDay();
	}
	
	,
	minusOneDay: function()
	{
		if (this.day > 1)
			this.day--;
		else
		{
			this.minusOneMonth();
			this.day = this.getMaxDayOfMonth(this.month);
		}
	}
	
	,
	minusOneMonth: function()
	{
		if (this.month > 1)
			this.month--;
		else
		{
			this.minusOneYear();
			this.month = 12;
		}
	}
	
	,
	minusOneYear: function()
	{
		if (this.year > 0)
			this.year--;
	}
	
	,
	addOneDay: function()
	{
		if (this.day < this.getMaxDayOfMonth(this.month))
			this.day++;
		else
		{
			this.addOneMonth();
			this.day = 1;
		}
	}
	
	,
	addOneMonth: function()
	{
		if (this.month < 12)
			this.month++;
		else
		{
			this.year++;
			this.month = 1;
		}
	}
	
	,
	addOneYear: function()
	{
		this.year++;
	}
	
	,
	isLeapYear: function()
	{
		if (-1 == this._ily)
		{
			if (this.year % 400 == 0)
				this._ily = 0;
			else if (this.year % 100 == 0)
				this._ily = 1;
			else if (this.year % 4 == 0)
				this._ily = 0;
			else
				this._ily = 1;
		}
		return this._ily == 0;
	}
	
	,
	countPreviousLeapYear: function()
	{
		var total = this.year - 1;
		return Math.floor(total / 4) - Math.floor(total / 100) + Math.floor(total / 400);
	}
	
	,
	getDayInYear: function()
	{
		return this.getSumDayOfMonth(this.month - 1) + this.day;
	}
	
	,
	getSumDayOfMonth: function(month)
	{
		if (month > 12 || month < 0)
			return -1;
		if (this.isLeapYear())
			return LMONTH_SUM_DAY[month];
		return MONTH_SUM_DAY[month];
	}
	
	,
	getMaxDayOfMonth: function(month)
	{
		if(!month)
			month = this.month;
		if (month > 12 || month < 0)
			return -1;
		if (this.isLeapYear())
			return LMAX_DAY_IN_MONTH[month];
		return MAX_DAY_IN_MONTH[month];
	}
	
	,
	/**
	 * @return 0~6, 0 is mean sunday
	 */
	getWeekDay: function()
	{
		return this.getDayInAD() % 7;
	}
	
	,
	getMonthFirstWeekDay: function()
	{
		var wd = this.getWeekDay();
		if (this.day == 1)
			return wd;
		wd = wd - this.day % 7 + 1;
		if (wd < 0)
			return 7 + wd;
		return wd;
	}
	
	,
	getDayInAD: function()
	{
		if(this.year<1)
			return this.getDayInYear()-1;
		return (this.year - 1) * 365 + this.countPreviousLeapYear() + this.getDayInYear();
	}
	
	,
	getDay: function()
	{
		return this.day;
	}

	,
	setDay: function(day)
	{
		if (day < 1)
			this.day = 1;
		else
		{
			var max = this.getMaxDayOfMonth(this.month);
			if (day > max)
				this.day = max;
			else
				this.day = day;
		}
	}
	
	,
	getMonth: function()
	{
		return this.month;
	}

	,
	setMonth: function(month)
	{
		if (month < 1)
			this.month = 1;
		else if (month > 12)
			this.month = 12;
		else
			this.month = month;
		if(this.day>this.getMaxDayOfMonth())
			this.day = this.getMaxDayOfMonth();
	}

	,
	getYear: function()
	{
		return this.year;
	}

	,
	setYear: function(year)
	{
		this._ily = -1;
		if (year < 0)
			this.year = 0;
		else
			this.year = year;
		if(this.day>this.getMaxDayOfMonth())
			this.day = this.getMaxDayOfMonth();
	}
	
	,
	clone: function()
	{
		return new ihelpuoo.util.Date(this.year,this.month,this.day);
	}

	,
	equals: function(obj)
	{
		if (obj.year != this.year)
			return false;
		if (obj.month != this.month)
			return false;
		if (obj.day != this.day)
			return false;
		return true;
	}

	,
	compareTo: function(obj)
	{
		if (this.equals(date))
			return 0;
		if (year > date.year)
			return 1;
		if (month > date.month)
			return 1;
		if (day > date.day)
			return 1;
		return -1;
	}
	
	,
	toRegularString: function()
	{
		return this.year+"-"
				+(this.month<10?"0":"")
				+ this.month
				+"-"
				+(this.day<10?"0":"")
				+ this.day;
	}
	
	,
	toString: function()
	{
		return this.toRegularString();
	}
	
	,
	dump: function()
	{
		return this.toString();
	}
}